package com.yc.pos;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Handler;
import android.util.Log;

import com.attendance.sz.local.LocalCardRecordDao;
import com.attendance.sz.net.AbsAPICallback;
import com.attendance.sz.net.SmartAPI;
import com.attendance.sz.utils.*;
import com.attendance.sz.utils.Session;
import com.yc.utilslib.utils.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import rx.Subscriber;

/**
 * Created by Administrator on 2015-11-20.
 */
public class SocketClient {
    public static final int UPLOAD_RECORD_COMMAND = 0xd3;
    public static final int UPDATE_TIME_COMMAND = 0xd5;
    private final static String LOGTAG = SocketClient.class.getName();
    private boolean bRun = false;
    private Handler mHandler;
    private Context mContext;
    private Thread myConnectThread;
    private Socket mSocket = null;
    LocalCardRecordDao localCardRecordDao = null;
    private LinkedList<CommandMessage> mMessages = new LinkedList<CommandMessage>();
    private LinkedList<CommandMessage> autoMessages = new LinkedList<CommandMessage>();
    String on;

    //短连接
    public SocketClient(Context context, Handler handler) {
        this.mHandler = handler;
        mContext = context;
        localCardRecordDao = new LocalCardRecordDao();
        bRun = true;
        myConnectThread = new MyConnectThread();
        myConnectThread.start();
    }

    public void addUpdatTimeCommand() {
        SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");
        mMessages.add(new CommandMessage(UPDATE_TIME_COMMAND, df.format(new Date())));
    }

    public class CommandMessage {
        private int command;
        private Object message;

        public CommandMessage(int cmd, Object msg) {
            command = cmd;
            message = msg;
        }

        public int getCommand() {
            return command;
        }
        public Object getMessage() {
            return message;
        }
    }

    class MyConnectThread extends Thread {
        public void run() {
            // 由于按文档要求，所以与网络后台是短连接的

            while (bRun) {
                try {
                    Thread.sleep(2000);//线程暂停5，单位毫秒
                    ServerConmunication();//ServerConmunicationjni();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    private long lastUploadTime = 0;
    private long startFreeTime = 0;
    private static final long FREE_TIME = 5 * 1000;

    private void ServerConmunication() {
        String strServer = Version.GetSeverIp();
        int iPort = Integer.valueOf(Version.GetSeverPort());
        int iTimeout = Integer.valueOf(Version.GetOverTime()) * 1000;
        SocketAddress remoteAddr = new InetSocketAddress(strServer, iPort);

        if (mMessages.size() == 0) {
            //TODO 加载本地无上传 记录----
            mMessages.addAll(loadRecordMessage());
        }
        if (mMessages.size() > 0) {
            mSocket = new Socket();
            try {
                mSocket.connect(remoteAddr, iTimeout);
                Log.d("TAG","iTimeout:"+iTimeout);
                if (mSocket.isConnected()) {
                    handleCommandMessage();
                }
                mSocket.close();
            } catch (Exception e) {
                logMa.d("socketclient", e.getMessage());
            }
            lastUploadTime = android.os.SystemClock.uptimeMillis();
        } else {
            //空闲，无等待上传的消息，则自动上传一次记录
            startFreeTime = android.os.SystemClock.uptimeMillis();
        }

    }

    private void autoUplaodRecord(CommandMessage cmd) {
        Record record = (Record) cmd.message;
        Packet ret = uploadRecordToServer(record);
        if (ret != null) {
            if (ret.state == 0x01 && ret.cmd == UPLOAD_RECORD_COMMAND) {
                logMa.d(LOGTAG, "auto upload record success:" + record.id);
                autoMessages.removeFirst();
                int index = Integer.valueOf(com.attendance.sz.utils.Session.getAutoUploadNum());
                com.attendance.sz.utils.Session.setAutoUploadNum(String.valueOf(index + 1));

            } else if (ret.state == 0x00 && ret.cmd == UPLOAD_RECORD_COMMAND) {
                logMa.d(LOGTAG, "auto upload record fail:" + record.id);
                localCardRecordDao.UpdateUploadFailCount(record.id);
            }
        }
    }

    private void handleCommandMessage() {
        if (mMessages.size() > 0) {
            CommandMessage cmd = mMessages.getFirst();
            switch (cmd.command) {
                case UPLOAD_RECORD_COMMAND:
                    uploadRecord(cmd);
                    break;
                case UPDATE_TIME_COMMAND:
                    updateTime((String) cmd.message);
                    break;
                default:
                    break;
            }
        }
    }

    private void uploadRecord(CommandMessage cmd) {
        Record record = (Record) cmd.message;
        Packet ret = uploadRecordToServer(record);
        if (ret != null) {
            if (ret.state == 0x01 && ret.cmd == UPLOAD_RECORD_COMMAND) {
                logMa.d(LOGTAG, "upload record success:" + record.id);
                if (localCardRecordDao.UpdateCardRecordFlag(record.id)) {
                    mMessages.removeFirst();
                }

            } else if (ret.state == 0x00 && ret.cmd == UPLOAD_RECORD_COMMAND) {
                logMa.d(LOGTAG, "upload record fail:" + record.id);
                localCardRecordDao.UpdateUploadFailCount(record.id);
            }
        }
    }

    private List<CommandMessage> loadRecordMessage() {
        List<CommandMessage> records = new ArrayList<CommandMessage>();
        Cursor cursor = null;
        try {
            cursor = localCardRecordDao.GetCardRecordCursonEx(0, 5);
            if (cursor != null) {
                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {

                    if (StringUtils.isNullOrEmpty(cursor.getString(cursor.getColumnIndex("card_no")))) {
                        localCardRecordDao.UpdateCardRecordFlag(cursor.getString(cursor.getColumnIndex("id")));
                        break;
                    }

                    Record record = new Record();
                    record.id = cursor.getString(cursor.getColumnIndex("id"));
                    record.recordNo = cursor.getString(cursor.getColumnIndex("card_no"));
                    record.time = cursor.getString(cursor.getColumnIndex("create_time"));
                    record.address = cursor.getString(cursor.getColumnIndex("device_no"));
                    Log.d("TAG","create_time:"+cursor.getString(cursor.getColumnIndex("create_time")));
                    records.add(new CommandMessage(UPLOAD_RECORD_COMMAND, record));

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return records;
    }

    private List<CommandMessage> loadRecordMessageAuto(int index) {
        List<CommandMessage> records = new ArrayList<CommandMessage>();
        Cursor cursor = null;
        try {
            cursor = localCardRecordDao.GetCardRecordCursonAuto(index, 5);
            if (cursor != null) {
                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                    Record record = new Record();
                    record.id = cursor.getString(cursor.getColumnIndex("id"));
                    record.recordNo = cursor.getString(cursor.getColumnIndex("card_no"));
                    record.time = cursor.getString(cursor.getColumnIndex("create_time"));
                    record.address = cursor.getString(cursor.getColumnIndex("device_no"));
                         on= cursor.getString(cursor.getColumnIndex("create_time"));
                    records.add(new CommandMessage(UPLOAD_RECORD_COMMAND, record));

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return records;
    }


    private Packet uploadRecordToServer(Record record) {
        int itimeout = Integer.valueOf(Version.GetOverTime()) * 1000;
        Packet packet = new Packet(UPLOAD_RECORD_COMMAND, record.encode());
        Packet ret = sendToServer(mSocket, packet, itimeout);
        Log.d("TAG","iTimeout1:"+itimeout);
        return ret;
    }

    //同步时间
    private void updateTime(String time) {
        int itimeout = Integer.valueOf(Version.GetOverTime()) * 1000;
        Packet packet = new Packet(UPDATE_TIME_COMMAND, time.getBytes());
        Packet ret = sendToServer(mSocket, packet, itimeout);
        Log.d("TAG","iTimeout2:"+itimeout);
        if (ret != null) {
            if (ret.state == 0x01 && ret.cmd == UPDATE_TIME_COMMAND) {
                logMa.d(LOGTAG, "update time success");
                Calendar cal = Calendar.getInstance();
                int year = 2000 + ret.data[0];
                int month = ret.data[1];
                int day = ret.data[2];
                int hour = ret.data[3];
                int min = ret.data[4];
                int sec = ret.data[5];
                cal.clear();
                cal.set(year, month - 1, day, hour, min, sec);
                SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd.HHmmss");
                String rettime = df.format(cal.getTime());
                Intent intent = new Intent("com.message.updatetime");
                intent.putExtra("time", rettime);
                mContext.sendBroadcast(intent);
            }
        }
        mMessages.removeFirst();
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                addUpdatTimeCommand();
            }
        }, 1000 * 60 * 60 * 2);  //2小时同步一次
    }
    int i = 0;
    Map<String,String> map = new HashMap<>();
    List<Map> list=new ArrayList<>();

    private Packet sendToServer(Socket soc, Packet packet, int delay) {
        OutputStream out = null;
        InputStream in = null;
        Packet ret = null;
        try {
            if (soc.isConnected()) {
                in = soc.getInputStream();
                out = soc.getOutputStream();
            }
            if (in == null || out == null) {
                return null;
            }

            // send
            logMa.d(LOGTAG, "SendToServer:" + DigitalUtil.Bytes2HexString(packet.encode()));
            byte[] mypacket = packet.encode();
            out.write(mypacket);
            out.flush();

            long lnow = android.os.SystemClock.uptimeMillis(); // 起始时间
            long lnew = android.os.SystemClock.uptimeMillis(); // 结束时间

            // recv
            int count = in.available();
            while (count == 0) {

                count = in.available();
                lnew = android.os.SystemClock.uptimeMillis();
                if (lnew - lnow > delay) {
                    logMa.d(LOGTAG, "Timoutt!!!:");
                    return null;

                }
            }

            count = in.available();
            if (count > 0) {
                byte[] return_d = new byte[count];// 默认最带为256
                in.read(return_d);
                ret = new Packet(DigitalUtil.Bytes2HexString(return_d));

                logMa.d("TAG", "RecFromServer:" + ClsPublic.Bytes2HexString(return_d));
                logMa.d("TAG", "RecordId:" + ByteUtils.byteArrayToLong(return_d, 9, 8));

                if (Session.getEnableCameraValue() == "1") {
                    map.put(on, MyApplication.getApp().getPoto());
                    list.add(map);

                    if (list.size() == 0) {
                        i = 0;
                    }

                    if (list.size() != 0) {
                        setImgview(ByteUtils.byteArrayToLong(return_d, 9, 8) + "", list.get(i).get(on) + "");
                    }
                }

                Log.d("TAG","On:" + on);
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return ret;
    }

 private  void   setImgview(String FileName ,String Buffer ){
     Subscriber subscriber = new AbsAPICallback<Entity>(mContext) {
         @Override
         public void onCompleted() {

         }

         @Override
         public void onNext(Entity entity) {
             Log.d("TAG","返回：" + entity.getReturnMsg());
             if (list.size() != 0){
                 list.remove(i);
             }
             i++;

             if (list.size() == 0 || list.size() == i){
                 i=0;
             }
             Log.d("TAG","i:" + i);
         }

         @Override
         public void onError(Throwable e) {
             super.onError(e);
             Log.d("TAG","错误："+e.getMessage());
         }
     };

     SmartAPI.getInstance().queryAccountInfo(subscriber,FileName,Buffer);
 }
    public void CloseSocket() {
        bRun = false;
        if (myConnectThread != null) {
            myConnectThread.interrupt();
        }

    }
}
